/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#include "lab_engine.h"

#include "aircraft_agent.h"
#include "airspace.h"
#include "canvas.h"
#include "clock.h"

#include "logging/logger.h"


using namespace atc;
using std::make_pair;
using std::string;


////////////////////////////////////////////////////////////////////////////////
//
// atc::LabEngine
//
//------------------------------------------------------------------------------
// [public] construction
//

/*!
 *
 */
LabEngine::LabEngine()
	  : _airspace()
	  , _canvas()
	  , _clock()
{}

/*!
 *
 */
LabEngine::~LabEngine() {}


//------------------------------------------------------------------------------
// [public] intialization - builder interface
//

/*!
 * Set the airspace for the engine
 *
 * The engine will take ownership of the airspace.
 *
 * @param airspace is a valid airspace
 */
void LabEngine::set_airspace( Airspace* airspace ) { 
	_airspace = airspace;
	_airspace->initialize();
	initalize_visualizer();

	connect( 
		    _airspace, SIGNAL ( event_recorded    ( KeyValues & ) )
		  , this,           SLOT   ( handle_information( KeyValues & ) )
	);
}

/*!
 * Set the canvas visualizer for the engine
 *
 * The engine will take ownership of the canvas.
 *
 * @param canvas is a valid canvas
 */
void LabEngine::set_canvas( Canvas* canvas ) {
	_canvas = canvas;
	initalize_visualizer();

	connect( 
		    _canvas, SIGNAL ( event_recorded    ( KeyValues & ) )
		  , this,         SLOT   ( handle_information( KeyValues & ) )
	);
}

/*!
 * Set the clock for the engine
 *
 * The engine will take ownership of the clock.
 *
 * @param clock 
 */
void LabEngine::set_clock( Clock* clock ) {
	_clock = clock;
	connect( 
			_clock,    SIGNAL( tick( int ) )
		  , _airspace, SLOT( advance( int ) ) 
	);
	connect( 
		    _clock, SIGNAL ( event_recorded    ( KeyValues & ) )
		  , this,         SLOT   ( handle_information( KeyValues & ) )
	);
	
	initalize_visualizer();
}


//------------------------------------------------------------------------------
// [public]
//

/*!
 *
 */
void LabEngine::start() { _clock->start(); }
void LabEngine::stop()  { _clock->stop(); }

//void LabEngine::lauch_aircraft() { _airspace->launch_aircraft(); }

//--------------------------------------------------------------------------------------------------
// [public] slots:
//

/*!
 *
 */
void LabEngine::handle_information( KeyValues &kvs ) {
	kvs.push_front( make_pair( string( "elapsed_time" ), to_string( _clock->elapsed_time() ) ) );

	logging::KVPairs data;
	for ( KeyValues::const_iterator kv = kvs.begin(); kv != kvs.end(); ++kv ) data.push_back( *kv );
	logging::Logger::instance()->info( data );

	//emit state_data( kvs );
}


//--------------------------------------------------------------------------------------------------
// [private] implementation
//

/*!
 * Initialize the visualizer
 *
 * Create visual representation for each aircraft in airspace and connect
 * signal/slot mechanisms.
 */
void LabEngine::initalize_visualizer() {
	if ( ! _canvas || ! _airspace || ! _clock ) return;

	// add aircraft to canvas
	Airspace::iterator ac = _airspace->begin();
	for ( ; ac != _airspace->end(); ++ac ) {
		_canvas->add_aircraft( ac->second );
	}

	//
	_canvas->update_aircraft();

	//
	QObject::connect( 
			_airspace, SIGNAL( advanced() )
		  , _canvas, SLOT( update_aircraft() )
	);

	QObject::connect(
			_canvas, SIGNAL( pause_request() ) 
		  , _clock, SLOT( stop() )
	);
	QObject::connect(
			_canvas, SIGNAL( resume_request() )
		  , _clock, SLOT( start() )
	);
	QObject::connect(
		    _clock, SIGNAL( seconds( long ) )
		  , _canvas, SIGNAL( sig_update_clock( long ) )
	);
	QObject::connect(
		    _clock, SIGNAL( stopped() )
		  , _canvas, SIGNAL( sig_stop_clock() )
	);
	QObject::connect(
		    _clock, SIGNAL( started() )
		  , _canvas, SIGNAL( sig_start_clock() )
	);

}
////////////////////////////////////////////////////////////////////////////////
